
package simuri.controller;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.HashMap;
import java.util.TreeSet;
import org.apache.log4j.Logger;
import simuri.NER.NerTool;
import simuri.NER.NerToolFactory;
import simuri.apriori.AprioriFunction;
import simuri.apriori.AprioriFunctionFactory;
import simuri.coherence.CoherenceFunction;
import simuri.coherence.CoherenceFunctionFactory;
import simuri.coherence.CoherenceMatrix;
import simuri.disambiguation.AlgorithmFactory;
import simuri.similarity.DbSimilarityFunction;
import simuri.similarity.DbSimilarityFunctionFactory;
import simuri.utils.Configuration;
import simuri.utils.EntityUriMap;
import simuri.utils.NamedEntity;

/**
 * Implements a generic disambiguation controller. Simply makes clear how the parts
 * interact. The server version should
 * - Rely on indexed label data to ensure improved runtimes
 * - A priori score data could also be precomputed
 * @author ngonga & fomy
 */
public class GenericController {
    
     static Logger logger = Logger.getLogger("AEON");

    /** Runs the named entity disambiguation
     * @param config Contains all the information necessary to carry out a NED task, incl.
     * inputText Text in which the entities are contained
     * nerTool Name of the NER tool to be used
     * similarity Similarity function to be used
     * coherence Coherence function to be used
     * apriori A-priori function to be used
     * algorithm Algorithm to utilized
     * sparqlEndpoint Endpoint of the knowledge base to utilize
     * graph Graph in the knowledge baed
     * labelProperties Name of properties used for labeling (rdfs:label, 
     * dc:title, etc.)
     * @return A mapping of named entities and URIs including scores
     */
    public static EntityUriMap run(Configuration config) {
        
    
        logger.info("1. Getting Named Entities");
        //1. get NEs
        NerTool ner = NerToolFactory.get(config.nerTool);
        TreeSet<NamedEntity> namedEntities = ner.getNEs(config.inputText);
        logger.info("Got entities " + namedEntities);
        if (namedEntities.isEmpty()) {
            return null;
        }
   
        logger.info("2. Getting candidates URIs");
        //2. Get all mapping uris including their similarity to the named entities
        long before2 = System.currentTimeMillis();
        DbSimilarityFunction simFunction = DbSimilarityFunctionFactory.get(config.similarity);

        EntityUriMap mappingUriSet = simFunction.getMappings(config, namedEntities);
        logger.info("Got following URIs: " + mappingUriSet);
        logger.info("3. Getting a-priori score for candidate URIs");
        
        //3. Get apriori score
        AprioriFunction aprioriFunction = AprioriFunctionFactory.get(config.apriori);
        HashMap<String, Double> aprioriScores;
        
        if (config.algorithm.startsWith("weighted") || config.algorithm.startsWith("norma")
                || config.algorithm.startsWith("linear") || config.algorithm.startsWith("aprio")){
            aprioriScores = aprioriFunction.getDbAprioriScore1(mappingUriSet.getAllUris(),config);
        } else {
            aprioriScores = null;
        }
        logger.info("Got the following a-priori scores: " + aprioriScores);
        //System.exit(1);
        logger.info("4. Computing coherence score for candidate URIs");
        //4. Get coherence matrix
        CoherenceFunction coherenceFunction = null;
        CoherenceMatrix coherenceMatrix = null;
        if (config.algorithm.startsWith("weighted") || config.algorithm.startsWith("norma")
                || config.algorithm.startsWith("global")) {
            coherenceFunction = CoherenceFunctionFactory.get(config.coherence);
            coherenceMatrix = coherenceFunction.getDbCoherence(aprioriScores.keySet(),
                    config);
        }
        logger.info("Got the following coherence matrix: " + coherenceMatrix);
        logger.info("5. Running disambiguation algorithm");
        //5. Run algorithm and return results        
        EntityUriMap result = AlgorithmFactory.get(config.algorithm).getMapping(mappingUriSet,
                coherenceMatrix, aprioriScores, config);

        return result;
    }
    
    
   public static String  annotateCorpus1(String input, String algorithm) {
        
        Configuration config = new Configuration();
        config.algorithm = algorithm;
        config.apriori = "dbedgecount";
        config.coherence = "dbedgecount";
        config.graph = null;
        config.nerTool = "fox";
        config.similarity = "dbtrigrams";
        config.sparqlEndpoint = "http://dbpedia.org/sparql";

        HashMap<NamedEntity, String> results;
        TreeSet<NamedEntity> nes;
        String output = null;
        if(input != null) {
        config.inputText = input;
        results = run(config).getBestMapping();
        String copy = input + "";
        nes = new TreeSet<>();
        for (NamedEntity ne : results.keySet()) {
            nes.add(ne);
        }
        //now rewrite string
        StringBuilder b = new StringBuilder(copy);
        System.out.println(nes);
        String color = "green";
        for (NamedEntity ne : nes) {
            System.out.println(ne);
            if (!copy.substring(0, ne.offset+ne.label.length()).contains("[")) {
                copy = copy.substring(0, ne.offset) + "[" + "<font color="+color+">" + ne.label + "</font>"+"," 
                        + ne.type + ", " + "<a href="+results.get(ne)+">"+ results.get(ne).replaceAll("http://dbpedia.org/resource/", "")+ "</a>"+ "]"
                        + copy.substring(ne.offset + ne.label.length());
            }
            output = copy;
        }
    }
          return output;  
    } 

} 
    

